home *** CD-ROM | disk | FTP | other *** search
- name putenv
- page 55,132
- title PUTENV modify environment variable
- ;
- ; PUTENV.ASM --- add or modify environment variable
- ;
- ; (C) 1987 Ziff Communications Co, by Ray Duncan
- ;
- ; Call with: DS:SI = new ASCIIZ environment variable
- ; ES = segment of program segment prefix
- ;
- ; Returns: AX = 0 if successful, -1 if failed
-
- DGROUP group _DATA
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT
-
- public putenv ; make visible to Linker
-
- extrn getenv:near
-
- ; names for working storage
- oldenv equ [bp-2] ; segment of old environment
- envlen equ [bp-4] ; length of old environment
- newenv equ [bp-6] ; segment of new environment
- pspseg equ [bp-8] ; segment of program segment prefix
- oldlen equ [bp-10] ; length of existing variable
- newlen equ [bp-12] ; length of new env. variable
- newname equ [bp-14] ; offset of new name portion
- newvar equ [bp-16] ; offset of new param. portion
-
- putenv proc near ; modify/add environment variable
-
- push bp ; set up stack frame for
- mov bp,sp ; working storage
- sub sp,16
-
- mov newname,si ; save offset of new variable
- mov pspseg,es ; save PSP segment
- mov es,es:[002ch] ; pick up segment of old
- mov oldenv,es ; environment and save it
-
- push cx ; save other registers
- push si
- push di
-
- ; find old environment length
- mov cx,8000h ; assume max = 32 KBytes
- xor di,di ; ES:DI = environment base
- xor al,al
- put1: repne scasb ; scan for double null (can't use
- scasb ; SCASW since might be on odd addr)
- jne put1
-
- mov envlen,di ; save length of old environment
-
- mov di,si ; find length of new env. variable
- mov ax,ds ; ES:DI = addr of new variable
- mov es,ax
- mov cx,-1
- xor al,al
- repne scasb ; scan for terminating null byte
- not cx ; now CX = length including null
- mov newlen,cx ; save length of new variable
-
- ; attempt to allocate memory
- ; block for new environment...
- mov bx,cx ; length of old environment
- add bx,envlen ; + length of new variable
- mov cl,4 ; divide by 16 and round
- shr bx,cl ; up to find paragraphs to
- inc bx ; allocate for new environment
- mov ah,48h ; Fxn 48h=allocate memory block
- int 21h ; transfer to MS-DOS
- jnc put2 ; jump if allocation succeeded
-
- mov ax,-1 ; otherwise, return error flag
- jmp put6
-
- put2: mov newenv,ax ; save new environment segment
-
- mov di,offset envar ; copy name portion of new
- ; variable to local storage
-
- put3: movsb ; copy characters up to '='
- cmp byte ptr [si],'='
- jne put3 ; loop until end of name found
- xor al,al ; append null byte to name
- stosb
-
- inc si ; save address of param.
- mov newvar,si ; portion of new variable
-
- mov si,offset envar ; check if new environment
- mov es,oldenv ; variable has a previous value
- call getenv ; in old environment
- mov oldlen,ax ; save length of value, if any
-
- or ax,ax ; was it present in old block?
- jnz put4 ; yes, PUTENV the hard way
-
- push ds ; no just copy existing environment
- ; and add the new variable
-
- mov ds,oldenv ; DS:SI = old env. block
- mov es,newenv ; ES:DI = new env. block
- mov cx,envlen ; CX = length of old environment
- dec cx ; less the extra null byte
- xor si,si
- xor di,di
- rep movsb ; copy the old stuff
-
- pop ds ; DS:SI = address of new variable
- mov si,newname ; ES:DI = end of new environment
- mov cx,newlen ; CX = length of new variable
- rep movsb ; append the new variable
- xor al,al ; and the extra null byte
- stosb ; marking end of environment
- jmp put5 ; go update PSP env. pointer
-
- put4: ; come here on the messy case,
- ; env. variable already exists
- ; ES:DI = offset+1 of '=' in
- ; old variable from 'getenv'
-
- push ds ; copy old environment to new
- mov ax,es ; up through the '=' of the
- mov ds,ax ; variable we are changing
- mov cx,di ; DS:SI = old environment
- mov es,newenv ; ES:DI = new environment
- xor si,si ; CX = offset+1 of '='
- xor di,di ; in old variable
- rep movsb
-
- pop ds ; now let DS:SI = offset+1
- push si ; of '=' in new variable
- mov si,newvar ; and CX = length of portion
- mov cx,newname ; following the '='
- add cx,newlen
- sub cx,newvar ; copy the new parameter portion
- rep movsb ; to the new environment
-
- pop si ; skip over parameter portion
- add si,oldlen ; of the old variable
- inc si ; and its null byte
-
- push ds ; now copy remainder of
- mov ds,oldenv ; old environment to new one
- mov cx,envlen ; total length less portion
- sub cx,si ; already copied and length
- rep movsb ; of old environment variable
- pop ds
-
- put5: ; PUTENV function successful,
- mov es,oldenv ; release old environment block
- mov ah,49h
- int 21h ; transfer to MS-DOS
-
- mov es,pspseg ; update pointer to new
- mov ax,newenv ; environment in caller's PSP
- mov es:[002ch],ax
-
- xor ax,ax ; return success code
-
- put6: pop di ; restore registers
- pop si
- pop cx
- mov sp,bp ; discard stack frame
- pop bp
- ret ; back to caller
-
- putenv endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- envar db 80 dup (0) ; name of new environment var.
- ; for call to 'getenv'
- _DATA ends
-
- end